#include <queue>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN=20000+10;
const int MAXB=25;

int N, IDX;

struct Node {
	LL val; int idx;
	Node(LL _v, int _i):val(_v),idx(_i){}
	bool operator<(const Node &t) const {
		if (val==t.val) return (idx<t.idx);
		else return (val<t.val);
	}
};

priority_queue<Node> Q;

struct Point {
	int x, y, idx;
	Point (){}
	Point(LL x, LL y):x(x), y(y) {}
	bool operator / (Point oth) {
		return (LL)x*oth.y>(LL)y*oth.x;
	}
	LL operator ^ (Point oth) {
		return (LL)x*oth.y-(LL)y*oth.x;
	}
	Point operator - (Point oth) {
		return Point(x-oth.x, y-oth.y);
	}
}A[MAXN], P[MAXN], KD[MAXN<<2];

struct Region {
	int M;
	Point B[MAXB];
};

bool son[MAXN<<2];

bool cmpX(const Point &a, const Point &b) {
	return (a.x<b.x||(a.x==b.x&&a.y<b.y)||(a.x==b.x&&a.y==b.y&&a.idx<b.idx));
}

bool cmpY(const Point &a, const Point &b) {
	return (a.y<b.y||(a.y==b.y&&a.x<b.x)||(a.y==b.y&&a.x==b.x&&a.idx<b.idx));
}

inline LL sqr(LL x) {
	return x*x;
}

void build(int rt, int l, int r, int k) {
	if (l>r) return; son[rt]=true;
	int mid=(l+r)>>1;
	nth_element(P+l, P+mid, P+r+1, k?cmpY:cmpX);
	KD[rt]=P[mid];
	build(rt<<1, l, mid-1, k^1);
	build(rt<<1|1, mid+1, r, k^1);
}

void query(int rt, int now, Point ask) {
	if (!son[rt]) return;
	int ls=rt<<1, rs=(rt<<1|1), need=0;
	Node tmp=Node(0, KD[rt].idx);
	tmp.val=sqr(ask.x-KD[rt].x)+sqr(ask.y-KD[rt].y);
	LL dist=ask.x-KD[rt].x;
	if (now) dist=ask.y-KD[rt].y;
	if (dist>=0) swap(ls, rs);
	query(ls, now^1, ask);
	if ((int)Q.size()<2) Q.push(tmp), need=1;
	else {
		if (tmp<Q.top()) Q.pop(), Q.push(tmp);
		if (sqr(dist)<Q.top().val) need=1;
	}
	if (need) query(rs, now^1, ask);
}

bool fitInRange(Point o, Point a, Point b) {
	if (a.x > b.x) swap(a.x, b.x);
	if (a.y > b.y) swap(a.y, b.y);
	return a.x <= o.x && o.x <= b.x && a.y <= o.y && o.y <= b.y;
}
 
bool onSeg(Point o, Point a, Point b) {
	return !((b - o) ^ (a - o)) && fitInRange(o, a, b);
}
 
bool inPoly(int n, Point *p, Point o) {
	bool ret = 0;
	for (int i=0; i<n; i++) {
		Point a = p[i], b = p[(i + 1) % n];
		if (onSeg(o, a, b)) return 1;
		if (a.y > b.y) swap(a, b);
		ret ^= a.y != b.y && a.y != o.y && a.y <= o.y && o.y <= b.y && ((b - a) / (o - a));
	}
	return ret;
}

void solve(int R_id) {
	printf("Region %d\n", R_id);
	Region R; scanf("%d", &R.M);
	for (int i=0; i<R.M; i++) scanf("%d%d", &R.B[i].x, &R.B[i].y);
	int cnt=0;
	for (int i=1; i<=N; i++) 
		if (inPoly(R.M, R.B, A[i])) P[++cnt]=A[i];
	assert(cnt>=2);
	memset(son, 0, sizeof(son));
	build(1, 1, cnt, 0);
	int M; scanf("%d", &M);
	while (M--) {
		Point ask; scanf("%d%d", &ask.x, &ask.y);
		while (!Q.empty()) Q.pop();
		query(1, 0, ask);
		int ans[2];
		ans[1]=Q.top().idx; Q.pop();
		ans[0]=Q.top().idx; Q.pop();
		printf("%d %d\n", ans[0], ans[1]);
	}
}

int main() {
	int T; scanf("%d", &T);
	for (int cas=1; cas<=T; cas++) {
		printf("Case #%d:\n", cas);
		scanf("%d", &N);
		for (int i=1; i<=N; i++) {
			scanf("%d%d", &A[i].x, &A[i].y);
			A[i].idx=i;
		}
		int R; scanf("%d", &R);
		for (int i=1; i<=R; i++) solve(i);
	}
	return 0;
}
